<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta name="generator" content="HTML Tidy, see www.w3.org">
<meta http-equiv="Content-Type" content=
"text/html; charset=iso-8859-1">
<meta name="resource-type" content="document">
<meta name="description" content=
"Shared libraries in the ports tree">
<meta name="keywords" content="openbsd,ports,library">
<meta name="distribution" content="global">
<meta name="copyright" content=
"This document copyright 2001 by OpenBSD.">
<title>Handling shared libraries in the OpenBSD ports tree</title>
</head>
<body text="Black" bgcolor="White" link="#23238E">
<img height="30" width="141" src="../images/smalltitle.gif" alt=
"[OpenBSD]"> 

<h1>How to handle shared libraries in the ports tree</h1>

<h2>Understanding shared libraries number rules</h2>
Shared libraries are a bit tricky for a variety of reasons.
You must understand the library naming scheme:
<code>libfoo.so.major.minor</code>.
<p>
When you link a program, the linker <code>ld</code> embeds that information
in the created binary. You can see it with <code>ldd</code>.
Later, when you run that program, the dynamic linker
<code>ld.so</code> uses that information to find the right dynamic library:
<ul>
	<li>A library with the same exact major number is required.
	<li>A library with an equal or higher minor number is required.
</ul>
So, this means that <strong>all</strong> libraries with the same major
number and an equal or higher minor number <strong>must satisfy the 
binary API that the program expects</strong>.  If they do not, then your
port is broken. Specifically, it will break when users try to update their
system.
<p>
The rules for shared libraries are quite simple.
<ul>
	<li>If you add functions to the library, you must bump the
library minor number: a program that needs those functions has no way to
require it except by asking explicitly for at least this version.
	<li>If the existing API changes, that is, if any function signature
is altered, or if valid calling sequences are no longer valid, if a
type changes in an incompatible way, the library major number <strong>must
be bumped</strong>.
	<li>This includes removing old functions. Any function removal
should trigger a major number bump.
</ul>
<p>
Sometimes, it happens that a library is written as several files, and that
internal functions happen to be visible to communicate between those files.
Those function names traditionally begin with an underscore, and are not
part of the API proper.
<p>
Note that the library naming scheme is ubiquitous on OpenBSD platforms,
whether they be ELF or a.out.

<h2>Tweaking ports builds to achieve the right names</h2>
Quite a few ports need tweaks to build shared libraries correctly anyways.
Remember that building shared libraries should be done with
<code>gcc -shared -fpic|-fPIC -o libfoo.so.4.5 obj1 obj2</code>
<p>
Trying to rename the library after the fact to adjust the version number 
does not work: ELF libraries use some extra magic to set the library 
internal name, so you must link it with the correct version the first time.
<p>
On the other hand, remember that you can override Makefile variables from
the command line, by using <code>MAKE_FLAGS</code> in the port's Makefile.
This is quite valuable in, for instance, libtool-based ports, which provide
one such version variable for each library they create.
<p>
The best way to handle libtool-based ports is to set 
<code>USE_LIBTOOL=Yes</code>. This activates the ports tree version of libtool,
which handles most details automatically:
<ul>
	<li>libtool looks at <code>SHARED_LIBS</code> and automatically 
	replaces version numbers.
	<li>libtool produces a log of shared library building in
	<code>${WRKBUILD}/shared_libs.log</code> which can be directly
	included in the port's Makefile.
</ul>

<h2>Try putting all user visible libraries into /usr/local/lib</h2>
As a rule, requesting the user to add directories to their ldconfig path
is a very bad idea: all shared libraries that are linked directly to
programs should appear in /usr/local/lib.  However, it is quite possible
to use a symbolic link to the actual library. You should understand the
library lookup rules:
<ul>
	<li>At build time, <code>ld</code> uses <code>-L</code> flags
to set up paths to look for libraries. It stops looking as soon as
it finds a library that matches its requirements.
	<li>At run time, <code>ld.so</code> uses the information cached
through <code>ldconfig</code> to find the required library.
</ul>

So, let us assume you have two ports that provide two major versions of a
given library, say <code>qt.1.45</code> and <code>qt.2.31</code>.
Since both ports can be installed simultaneously, to make sure a given
program will link against qt.1, that library is provided as
<code>/usr/local/lib/qt/libqt.so.1.45</code>, and programs will be linked
using <code>ld -o program program.o -L/usr/local/lib/qt -lqt</code>.
Similarly, a program that links with qt.2 will use the 
<code>/usr/local/lib/qt2/libqt.so.2.31</code> file with
<code>ld -o program program.o -L/usr/local/lib/qt2 -lqt</code>.
<p>
To solve those libraries at run-time, a link called
<code>/usr/local/lib/libqt.so.1.45</code> and a link called
<code>/usr/local/lib/libqt.so.2.31</code> have been provided. This is
enough to satisfy <code>ld.so</code>.
<p>
It is an error to link a program using qt1 with
<code>ld -o program program.o -L/usr/local/lib -lqt</code>.
This code assumes the <code>qt.2.31</code> is not installed, which is
a wrong assumption.
<p>
Such tricks are only necessary in the rare cases of very pervasive
libraries where a transition period between major versions must be
provided. In general, it is enough to make sure the library appears in
<code>/usr/local/lib</code>.
<h2>Writing library dependencies correctly</h2>
The new dependency code does need complete library dependencies. You must
use <code>make lib-depends-check</code> to verify a port does mention all
libraries it requires. You just separate library specs with commas like
this:
<code>LIB_DEPENDS=gtk.1.2,gdk.1.2::x11/gtk+</code>.
<p>
It is not an error to specify static libraries on a LIB_DEPENDS line as
well. LIB_DEPENDS are fully evaluated at package build time: the resulting
package will have library dependency information embedded as lines for
<code>ld.so</code> that hold the actual major.minor number that was used
for building, and nothing for static libraries.
<p>
You must provide RUN_DEPENDS as well if a port requires anything beyond
a library proper. This will allow the port to build correctly on
architectures that do not support shared libraries.
<p>
In fact, providing LIB_DEPENDS lines for static libraries is a good idea:
this will simplify port update if a given dependency goes from a static
library to a shared library.
<p>
LIB_DEPENDS lines must specify the same paths that are used for 
<code>ld</code>. For instance, the standard qt2 depends fragment says: 
<code>LIB_DEPENDS+=lib/qt2/qt.2::x11/qt2</code>, so that the lib 
depends line will be solved correctly. This allows the dependency checking
code to do the right thing when multiple versions of the same library
are encountered.
<h2>Updating ports correctly</h2>
So, when you update or add a port that involves shared libraries, a few details
must be done right.
<ul>
	<li>Make sure the shared libraries major.minor numbers are correct.
	<li>Verify all ports that depend on your port. Verify that they
build correctly with your changes. Notify corresponding maintainers of the
update, so that they can verify their ports still run correctly.
	<li>You may have to adjust dependent ports LIB_DEPENDS. If you 
introduce new shared libraries, watch out for BUILD_DEPENDS that need to 
be turned into LIB_DEPENDS.
	<li>Whenever you introduce a new port, you should verify that you
are not creating a library that conflicts with an existing library:
libraries from two ports with the same name are deadly, because their
version numbering schemes have no chance to match.  You should try to solve
the situation with the software author (for instance, a library that is
called libnet is definitely badly named).
	<li>Check <a href="update.html">the ports update guidelines</a>
for a more extensive discussion.
</ul>
  <hr>
  <a href="../index.html"><img height=24 width=24 src=../back.gif border=0 alt=OpenBSD></a> 
  <a href="mailto:www@openbsd.org">www@openbsd.org</a>
<br><small>$OpenBSD: libraries.html,v 1.6 2006/11/04 10:53:37 espie Exp $</small>
 </body>
</html>
